package xyz.labmem.app.unit

import atlantafx.base.theme.Tweaks
import javafx.beans.property.SimpleListProperty
import javafx.beans.property.SimpleStringProperty
import javafx.beans.value.ObservableValue
import javafx.collections.FXCollections
import javafx.event.EventHandler
import javafx.geometry.Insets
import javafx.scene.Node
import javafx.scene.control.*
import javafx.scene.control.cell.TreeItemPropertyValueFactory
import javafx.scene.layout.HBox
import javafx.scene.paint.Color
import javafx.scene.text.Font
import javafx.util.Callback
import xyz.labmem.app.config.AppConfig
import xyz.labmem.app.config.AppConfig.mouseImage
import xyz.labmem.app.dialog.form.ClientConfigForm
import xyz.labmem.app.main.CenterPane
import xyz.labmem.app.main.MainStage
import xyz.labmem.app.util.mouseClickedPoll
import xyz.labmem.lipx.core.Status.*
import xyz.labmem.lipx.core.client.core.LabSSHPenetrationClient
import xyz.labmem.lipx.core.context.AppContext
import xyz.labmem.lipx.core.entity.ClientConfig
import xyz.labmem.lipx.core.util.ClientConfigDataUtil
import xyz.labmem.util.viewRun

class ProxyListUnit(parent: CenterPane) : HBox() {

    val data = SimpleListProperty<ClientConfig>(FXCollections.observableArrayList())

    val groupList: GroupListUnit

    companion object {
        private var thisObj: ProxyListUnit? = null
        fun refresh() {
            thisObj?.groupList?.refresh()
        }
    }

    init {
        thisObj = this
        prefHeightProperty().bind(parent.prefHeightProperty())
        prefWidthProperty().bind(parent.prefWidthProperty().subtract(230))
        groupList = GroupListUnit(this)
        children.add(groupList)

        //表单
        val treeTable = createTreeTable()
        treeTable.columnResizePolicy = TreeTableView.UNCONSTRAINED_RESIZE_POLICY
        children.add(treeTable)
        data.addListener { _, _, list ->
            //处理数据
            val root = TreeItem(ClientConfig().apply {
                serverHost = "Root"
            })
            list.map { item -> item.serverHost }.toSet().forEach {
                val child = list.filtered { item -> item.serverHost == it }
                val groupVal = ClientConfig()
                groupVal.serverHost = it
                groupVal.serverPort = child[0].serverPort
                groupVal.password = child[0].password
                groupVal.group = child[0].group
                groupVal.type = child[0].type
                val group = TreeItem(groupVal)
                group.children.setAll(child.map { m -> TreeItem(m) })
                group.expandedProperty().addListener { _, _, expanded ->
                    if (expanded) treeTable.refresh()
                }
                group.isExpanded = true
                root.children.add(group)
            }
            root.isExpanded = true
            treeTable.root = root
            treeTable.isShowRoot = false
        }
        //双击监听
        treeTable.rowFactory = Callback<TreeTableView<ClientConfig>, TreeTableRow<ClientConfig>> {
            TreeTableRow<ClientConfig>().apply {
                onMouseClicked = mouseClickedPoll { event ->
                    if (event.clickCount == 2 && !isEmpty) {
                        if (treeItem != null && treeItem.isLeaf) {
                            MainStage.formDialog(ClientConfigForm("修改", treeItem.value))
                        }
                    }
                }
            }
        }
    }

    private fun createTreeTable(): TreeTableView<ClientConfig> {
        val ttb = TreeTableView<ClientConfig>().apply {
            prefWidthProperty().bind(
                this@ProxyListUnit.prefWidthProperty().subtract(groupList.prefWidthProperty()).subtract(40)
            )
            prefHeightProperty().bind(this@ProxyListUnit.prefHeightProperty().subtract(40))
            setMargin(this, Insets(20.0, 20.0, 20.0, 20.0))
            styleClass.addAll(Tweaks.EDGE_TO_EDGE, Tweaks.ALT_ICON)
        }
        ttb.columns.setAll(
            TreeTableColumn<ClientConfig, String>("服务器地址").apply {
                cellValueFactory =
                    Callback<TreeTableColumn.CellDataFeatures<ClientConfig, String>, ObservableValue<String>> {
                        if (it.value.value.id == null)
                            SimpleStringProperty("${it.value.value.serverHost}")
                        else
                            SimpleStringProperty(": ${it.value.value.serverPort}")
                    }
                prefWidthProperty().bind(ttb.prefWidthProperty().multiply(.2))
                styleClass.addAll(Tweaks.ALIGN_CENTER)
            },
            TreeTableColumn<ClientConfig, String>("连接名称").apply {
                cellValueFactory = TreeItemPropertyValueFactory("remark")
                prefWidthProperty().bind(ttb.prefWidthProperty().multiply(.1))
                styleClass.addAll(Tweaks.ALIGN_CENTER)
            },
            TreeTableColumn<ClientConfig, String>("代理地址").apply {
                cellValueFactory =
                    Callback<TreeTableColumn.CellDataFeatures<ClientConfig, String>, ObservableValue<String>> {
                        SimpleStringProperty(if (it.value.value.proxyHost != null) "${it.value.value.proxyHost}:${it.value.value.proxyPort}" else "")
                    }
                prefWidthProperty().bind(ttb.prefWidthProperty().multiply(.25))
                styleClass.addAll(Tweaks.ALIGN_CENTER)
            },
            TreeTableColumn<ClientConfig, String>("转发端口").apply {
                cellValueFactory = TreeItemPropertyValueFactory("targetPort")
                prefWidthProperty().bind(ttb.prefWidthProperty().multiply(.1))
                styleClass.addAll(Tweaks.ALIGN_CENTER)
            },
            TreeTableColumn<ClientConfig, Node>("状态").apply {
                prefWidthProperty().bind(ttb.prefWidthProperty().multiply(.15))
                styleClass.addAll(Tweaks.ALIGN_CENTER)
                cellFactory =
                    Callback<TreeTableColumn<ClientConfig, Node>, TreeTableCell<ClientConfig, Node>> {
                        object : TreeTableCell<ClientConfig, Node>() {
                            override fun updateItem(p0: Node?, p1: Boolean) {
                                super.updateItem(p0, p1)
                                graphic = if (p1 || tableRow?.item?.id == null) null else {
                                    when (tableRow.item.status) {
                                        IDLE -> ProgressBar(.0)
                                        CONNECTING -> ProgressBar(-1.0)
                                        CONNECTED -> ProgressBar(100.0).apply {
                                            viewRun {
                                                lookup(".bar")?.style = "-fx-background-color: #32CD32;"
                                            }
                                        }

                                        RE_CONNECT -> ProgressBar(-1.0).apply {
                                            viewRun {
                                                lookup(".bar")?.style = "-fx-background-color: #FF8C00;"
                                            }
                                        }

                                        FAILED -> ProgressBar(50.0).apply {
                                            viewRun {
                                                lookup(".bar")?.style = "-fx-background-color: #DC143C;"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
            },
            TreeTableColumn<ClientConfig, HBox>("操作").apply {
                styleClass.addAll(Tweaks.ALIGN_CENTER)
                prefWidthProperty().bind(ttb.prefWidthProperty().multiply(.2).subtract(5))
                cellFactory =
                    Callback<TreeTableColumn<ClientConfig, HBox>, TreeTableCell<ClientConfig, HBox>> {
                        object : TreeTableCell<ClientConfig, HBox>() {
                            override fun updateItem(p0: HBox?, p1: Boolean) {
                                super.updateItem(p0, p1)
                                graphic = if (p1) null else {
                                    if (tableRow?.item?.id == null)
                                        HBox(
                                            makeTableBtn("添加", Color.BLACK, "white") {
                                                MainStage.formDialog(ClientConfigForm("添加", tableRow.item))
                                            }
                                        )
                                    else
                                        HBox(
                                            when (tableRow.item.status) {
                                                IDLE -> makeTableBtn("连接", Color.BLACK, "#ffe206") {
                                                    LabSSHPenetrationClient(tableRow.item) { refresh() }.connect()
                                                }

                                                CONNECTING -> makeTableBtn("断开", Color.WHITE, "#5e00ff") {
                                                    AppContext.Client.connectingList[tableRow.item.id]?.close()
                                                }

                                                CONNECTED -> makeTableBtn("断开", Color.WHITE, "#5e00ff") {
                                                    AppContext.Client.connectList[tableRow.item.id]?.close()
                                                }

                                                RE_CONNECT -> makeTableBtn("断开", Color.WHITE, "#5e00ff") {
                                                    AppContext.Client.connectList[tableRow.item.id]?.close()
                                                }

                                                FAILED -> makeTableBtn("连接", Color.BLACK, "#ffe206") {
                                                    LabSSHPenetrationClient(tableRow.item){ refresh() }.connect()
                                                }
                                            },
                                            makeTableBtn("删除", Color.WHITE, "#ff0000") {
                                                MainStage.confirmDialog(
                                                    "删除连接",
                                                    "【${tableRow.item.remark}】请确认！"
                                                ) {
                                                    try {
                                                        if (tableRow.item.status == CONNECTED || tableRow.item.status == CONNECTING)
                                                            AppContext.Client.connectList[tableRow.item.id]?.close()
                                                        ClientConfigDataUtil.delById(tableRow.item.id!!)
                                                        viewRun { refresh() }
                                                        MsgUnit.getMsgUnit().showMsg("删除成功了喵~")
                                                        true
                                                    } catch (e: Exception) {
                                                        e.printStackTrace()
                                                        MsgUnit.getMsgUnit().showMsg("删除失败了喵~")
                                                        false
                                                    }
                                                }
                                            },
                                        )
                                }
                            }
                        }
                    }
            },
        )
        return ttb
    }

    private fun makeTableBtn(text: String, tc: Color, bc: String, checkFun: () -> Unit): Label {
        return Label(text).apply {
            setMargin(this, Insets(5.0, 5.0, .0, .0))
            font = Font.loadFont(AppConfig.font, 18.0)
            textFill = tc
            style = "-fx-background-radius: 8 0 8 0;-fx-background-color:$bc;-fx-padding: 2 10;"
            onMouseClicked = mouseClickedPoll { checkFun() }
            onMouseEntered = EventHandler {
                MainStage.setCursor(mouseImage["m6"])
            }
            onMouseExited = EventHandler {
                MainStage.cursorBack()
            }
        }
    }

}